package chendu.service;

import chendu.entity.PhoneCategory;
import chendu.entity.PhoneInfo;
import chendu.entity.PhoneSpecs;
import chendu.enums.ResultEnum;
import chendu.exception.PhoneException;
import chendu.mapper.PhoneCategoryMapper;
import chendu.mapper.PhoneInfoMapper;
import chendu.mapper.PhoneSpecsMapper;
import chendu.util.PhoneUtil;
import chendu.vo.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Slf4j
@Service("service-phone")
public class PhoneServiceImpl implements PhoneService {

    @Autowired
    private PhoneCategoryMapper phoneCategoryMapper;
    @Autowired
    private PhoneInfoMapper phoneInfoMapper;
    @Autowired
    private PhoneSpecsMapper phoneSpecsMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    private ObjectMapper objectMapper=new ObjectMapper();
    private Map<String,Object> map=new HashMap<>();

    @Override
    public DataVO findDataVO() {
        DataVO dataVO = new DataVO();
        String key="allCategory";
        ValueOperations<String, String> opsForString = redisTemplate.opsForValue();
        List<PhoneCategory> phoneCategoryList;
        if(redisTemplate.hasKey(key)){
            String categoryJson = opsForString.get(key);
            try {
                phoneCategoryList = objectMapper.readValue(categoryJson, objectMapper.getTypeFactory().constructCollectionType(List.class,PhoneCategory.class));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                return null;
            }
        }else {
            phoneCategoryList = phoneCategoryMapper.selectList(null);
            try {
                String categoryJson=objectMapper.writeValueAsString(phoneCategoryList);
                opsForString.set(key,categoryJson,3, TimeUnit.DAYS);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                return null;
            }
        }



       /* List<PhoneCategoryVO> phoneCategoryVOList = new ArrayList<>();
        for (PhoneCategory phoneCategory : phoneCategoryList) {
            PhoneCategoryVO phoneCategoryVO = new PhoneCategoryVO();
            phoneCategoryVO.setCategoryName(phoneCategory.getCategoryName());
            phoneCategoryVO.setCategoryType(phoneCategory.getCategoryType());
            phoneCategoryVOList.add(phoneCategoryVO);
        }*/

        List<PhoneCategoryVO> phoneCategoryVOList =  phoneCategoryList.stream()
                .map(e -> new PhoneCategoryVO(
                        e.getCategoryName(),
                        e.getCategoryType()
                )).collect(Collectors.toList());

        dataVO.setCategories(phoneCategoryVOList);

        //手机
        /*
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("category_type",phoneCategoryList.get(0).getCategoryType());
        List<PhoneInfo> phoneInfoList = (List<PhoneInfo>) phoneInfoMapper.selectByMap(map);
        */
        List<PhoneInfo> phoneInfoList;
        String key2="category1";
        if(redisTemplate.hasKey(key2)){
            String categoryJsonForOne = opsForString.get(key2);
            try {
                phoneInfoList=objectMapper.readValue(categoryJsonForOne,objectMapper.getTypeFactory().constructCollectionType(List.class,PhoneInfo.class));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                return null;
            }
        }else {
            map.put("category_type",phoneCategoryList.get(0).getCategoryType());
            phoneInfoList = phoneInfoMapper.selectByMap(map);
            try {
                String categoryJsonForOne = objectMapper.writeValueAsString(phoneInfoList);
                opsForString.set(key2,categoryJsonForOne,3,TimeUnit.DAYS);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                return null;
            }

        }

        //常规写法
       /* List<PhoneInfoVO> phoneInfoVOList = new ArrayList<>();
        for (PhoneInfo phoneInfo : phoneInfoList) {
            PhoneInfoVO phoneInfoVO = new PhoneInfoVO();
            BeanUtils.copyProperties(phoneInfo,phoneInfoVO);
            phoneInfoVO.setTag(PhoneUtil.createTag(phoneInfo.getPhoneTag()));
            phoneInfoVOList.add(phoneInfoVO);
        }*/
        //stream
        List<PhoneInfoVO> phoneInfoVOList = phoneInfoList.stream()
                .map(e -> new PhoneInfoVO(
                        e.getPhoneId(),
                        e.getPhoneName(),
                        e.getPhonePrice()+".00",
                        e.getPhoneDescription(),
                        PhoneUtil.createTag(e.getPhoneTag()),
                        e.getPhoneIcon()
                )).collect(Collectors.toList());
        dataVO.setPhones(phoneInfoVOList);

        return dataVO;
    }

   @Override
    public List<PhoneInfoVO> findPhoneInfoVOByCategoryType(Integer categoryType) {
        String key="findAllByCategoryType"+categoryType;
        List<PhoneInfo> phoneInfoList;
       ValueOperations<String, String> opsForString = redisTemplate.opsForValue();
        if(redisTemplate.hasKey(key)){
            String findAllByCategoryTypeValue = opsForString.get(key);
            try {
                phoneInfoList = objectMapper.readValue(findAllByCategoryTypeValue,objectMapper.getTypeFactory().constructCollectionType(List.class,PhoneInfo.class));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                return null;
            }
        }else {
            phoneInfoList = phoneInfoMapper.findAllByCategoryType(categoryType);
            try {
                String findAllByCategoryTypeValue = objectMapper.writeValueAsString(phoneInfoList);
                opsForString.set(key,findAllByCategoryTypeValue,3,TimeUnit.DAYS);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                return null;
            }
        }

        List<PhoneInfoVO> phoneInfoVOList = phoneInfoList.stream()
                .map(e -> new PhoneInfoVO(
                        e.getPhoneId(),
                        e.getPhoneName(),
                        e.getPhonePrice()+".00",
                        e.getPhoneDescription(),
                        PhoneUtil.createTag(e.getPhoneTag()),
                        e.getPhoneIcon()
                )).collect(Collectors.toList());
        return phoneInfoVOList;
    }

    @Override
    public SpecsPackageVO findSpecsByPhoneId(Integer phoneId) {
            /*执行逻辑
            * 1、通过phoneId先查询phone_info,并判断是否查询成功
            * 2、在查询成功的基础上，再去通过phoneId查询phone_specs表*/
            PhoneInfo phoneInfo = phoneInfoMapper.findById(phoneId);

            if (phoneInfo == null){
                return null;
            }
            List<PhoneSpecs> phoneSpecsList = phoneSpecsMapper.findAllByPhoneId(phoneId);


            List<PhoneSpecsVO> phoneSpecsVOList = new ArrayList<>();
            List<PhoneSpecsCasVO> phoneSpecsCasVOList = new ArrayList<>();
            PhoneSpecsVO phoneSpecsVO;
            PhoneSpecsCasVO phoneSpecsCasVO;
            for (PhoneSpecs phoneSpecs : phoneSpecsList) {
                phoneSpecsVO = new PhoneSpecsVO();
                phoneSpecsCasVO = new PhoneSpecsCasVO();
                BeanUtils.copyProperties(phoneSpecs,phoneSpecsVO);
                BeanUtils.copyProperties(phoneSpecs,phoneSpecsCasVO);
                phoneSpecsVOList.add(phoneSpecsVO);
                phoneSpecsCasVOList.add(phoneSpecsCasVO);
            }
            TreeVO treeVO = new TreeVO();
            treeVO.setV(phoneSpecsVOList);
            List<TreeVO> treeVOList = new ArrayList<>();
            treeVOList.add(treeVO);

            SkuVO skuVO = new SkuVO();
            Integer price = phoneInfo.getPhonePrice().intValue();
            skuVO.setPrice(price+".00");
            skuVO.setStock_num(phoneInfo.getPhoneStock());
            skuVO.setTree(treeVOList);
            skuVO.setList(phoneSpecsCasVOList);

            SpecsPackageVO specsPackageVO = new SpecsPackageVO();
            specsPackageVO.setSku(skuVO);
            Map<String,String> goods = new HashMap<>();
            goods.put("picture",phoneInfo.getPhoneIcon());
            specsPackageVO.setGoods(goods);

            return specsPackageVO;

    }

    @Override
    public PhoneSpecs findSpecsById(Integer specsId) {
        return phoneSpecsMapper.findById(specsId);
    }

    @Override
    public PhoneInfo findPhoneById(Integer phoneId) {
        return phoneInfoMapper.findById(phoneId);
    }

    //查询库存剩余
   //@Override
    public void subStock(Integer specsId, Integer quantity) {
        /*执行逻辑
        * 1、通过商品的specsId 查询phone_specs表，获得库存
        * 2、通过phone_id查询phone_info表中的stock*/
        PhoneSpecs phoneSpecs = phoneSpecsMapper.findById(specsId);
        PhoneInfo phoneInfo = phoneInfoMapper.findById(phoneSpecs.getPhoneId());
        //查询手机规格表库存
        Integer result = phoneSpecs.getSpecsStock() - quantity;
        if(result < 0){
            log.error("【扣库存】库存不足");//
            throw new PhoneException(ResultEnum.PHONE_STOCK_ERROR);
        }

        phoneSpecs.setSpecsStock(result);
       System.out.println(result);
        phoneSpecsMapper.save(phoneSpecs.getSpecsStock(),phoneSpecs.getSpecsId());



        result = phoneInfo.getPhoneStock() - quantity;
        if(result < 0){
            log.error("【扣库存】库存不足");
            throw new PhoneException(ResultEnum.PHONE_STOCK_ERROR);
        }

        phoneInfo.setPhoneStock(result);
        phoneInfoMapper.save(phoneInfo.getPhoneStock(),phoneInfo.getPhoneId());
    }
}
